#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>

#define SERVER_IP "127.0.0.1"
#define TCP_PORT 5001
#define UDP_PORT 5002
#define BUFFER_SIZE 1024 * 1024

void tcp_client()
{
    int sockfd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE] = {0};
    int file_fd;
    ssize_t bytes_read;
    clock_t start, end;
    double cpu_time_used;

    /* 创建 TCP 套接字 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket creation error");
        exit(EXIT_FAILURE);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(TCP_PORT);

    /* 将 IPv4 地址从点分十进制转换为二进制形式 */
    if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0)
    {
        perror("Invalid address/ Address not supported");
        exit(EXIT_FAILURE);
    }

    /* 连接到服务器 */
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        perror("Connection Failed");
        exit(EXIT_FAILURE);
    }

    /* 打开要发送的文件 */
    if ((file_fd = open("large_file.bin", O_RDONLY)) < 0)
    {
        perror("file open failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    start = clock();
    /* 读取文件并发送 */
    while ((bytes_read = read(file_fd, buffer, BUFFER_SIZE)) > 0)
    {
        if (send(sockfd, buffer, bytes_read, 0) < 0)
        {
            perror("send failed");
            break;
        }
    }
    end = clock();

    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("TCP 发送时间: %f 秒\n", cpu_time_used);

    close(file_fd);
    close(sockfd);
}

void udp_client()
{
    int sockfd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE] = {0};
    int file_fd;
    ssize_t bytes_read;
    clock_t start, end;
    double cpu_time_used;

    /* 创建 UDP 套接字 */
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(UDP_PORT);
    inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr);

    /* 打开要发送的文件 */
    if ((file_fd = open("large_file.bin", O_RDONLY)) < 0)
    {
        perror("file open failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    start = clock();
    /* 读取文件并发送 */
    while ((bytes_read = read(file_fd, buffer, BUFFER_SIZE)) > 0)
    {
        if (sendto(sockfd, buffer, bytes_read, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
        {
            perror("sendto failed");
            break;
        }
    }
    end = clock();

    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("UDP 发送时间: %f 秒\n", cpu_time_used);

    close(file_fd);
    close(sockfd);
}

int main()
{
    /* 启动 TCP 客户端 */
    tcp_client();
    /* 启动 UDP 客户端 */
    udp_client();
    return 0;
}